package com.apes.fn.rpt.profit;

import com.alibaba.fastjson.JSONObject;
import com.apes.fn.rpt.profit.grossProfitProcess.CommonGrossProfitProcess;
import com.apes.fn.rpt.profit.grossProfitProcess.GrossProfitProcess;
import com.apes.fn.rpt.profit.grossProfitProcess.GrossProfitProcessFactory;
import com.apes.fn.rpt.profit.grossProfitProcess.processor.RetailExpense;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.Arith;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;

/**
 * 毛利报表
 * @author wuq
 * @Time 2022-10-20 14:33
 * @Description
 */
@Service
public class RptGrossProfitService {

    @Autowired
    private GrossProfitDao grossProfitDao;
    @Autowired
    private GrossProfitRepository grossProfitRepository;
    @Autowired
    private PartyRoleRepository partyRoleRepository;
    @Autowired
    private DeptRepository deptRepository;

    /**
     *
     */
    private static List<String> list = Arrays.asList(
            "LossSettle", "MoneyIncome", "BuyYearCard","InsuranceCommission","UsedCarServeFee",
            "VipCardPayment","VipCardUse","YearCardUse","Retail","VipUnionOut","VipUnionIn"
    );

    /**
     * 日结执行入口-新版
     * @param request taskDate
     */
    public void process(SimpleRequest request) {
        JSONObject param = request.getJO();
        Date taskDate = param.getDate("taskDate");
        processByDate(taskDate);
    }
    /**
     * 日结执行入口
     */
    public void processByDate(Date taskDate) {
        list.forEach( type -> {
            GrossProfitProcess process = GrossProfitProcessFactory.get(type);
            process.execute(taskDate,this::packSql);
        });
//        int i=1/0;
        //刷新已记账毛利
        grossProfitRefresh(taskDate);
    }
    /**
     * 日结执行入口
     */
    public void processByDateWithoutRefresh(Date taskDate) {
        list.forEach( type -> {
            GrossProfitProcess process = GrossProfitProcessFactory.get(type);
            process.execute(taskDate,this::packSql);
        });
//        int i=1/0;
        //刷新已记账毛利
//        grossProfitRefresh(taskDate);
    }
    /**
     * 获取统计sql
     */
    public Map getTotalSql(Date taskDate) {
        Map result = new HashMap();
        list.forEach( type -> {
            GrossProfitProcess process = GrossProfitProcessFactory.get(type);
            String sql = process.getSQL(taskDate);
            result.put(type,packSql(sql));
            if (type.equals("Retail")){
                process.changeType(RetailExpense.DOCUMENT_DATE_TYPE);
                result.put(type+"_DOCUMENT",packSql(process.getSQL(taskDate)));
            }


        });
        return result;
    }

    private String packSql(String sql){
        String s="SELECT Y.*," +
                "  (Y.PRICE_TOTAL - Y.CONSUMABLE_USE - Y.MAN_HOUR_COST -Y.ACCESSORY_COST - Y.PLATFORM_MANAGEMENT_FEE - Y.SUPPLY_CHAIN_MANAGEMENT_FEE + Y.VIP_IN +Y.VIP_OUT) GROSS_PROFIT," +
                "  (CASE WHEN (Y.PRICE_TOTAL + Y.VIP_IN +Y.VIP_OUT)=0 THEN 0 " +
                "  ELSE " +
                "(Y.PRICE_TOTAL - Y.CONSUMABLE_USE - Y.MAN_HOUR_COST - Y.ACCESSORY_COST - Y.PLATFORM_MANAGEMENT_FEE - Y.SUPPLY_CHAIN_MANAGEMENT_FEE + Y.VIP_IN +Y.VIP_OUT)/(Y.PRICE_TOTAL + Y.VIP_IN +Y.VIP_OUT)" +
                " END ) GROSS_RATE" +
                " FROM ( " +
                " " + sql+
                "       ) Y " +
                " WHERE Y.DEPT_ID IS NOT NULL " +
                "   AND Y.COMPANY_ID IS NOT NULL " +
                "   AND NVL(Y.AMOUNT, 0) + VIP_IN + VIP_OUT + CONSUMABLE_USE + ACCESSORY_COST + MAN_HOUR_COST + TIMES <> 0 " +
                "   ORDER BY DEPT_ID";
        return s;
    }

    /**
     * 已记账毛利报表刷新
     *
     * @param P_DATE
     */
    private void grossProfitRefresh(Date P_DATE) {
        GrossProfitProcess retail = GrossProfitProcessFactory.get("Retail");
        retail.changeType(RetailExpense.DOCUMENT_DATE_TYPE);
        String sql = packSql(retail.getSQL(P_DATE));
        grossProfitDao.queryGrossProfitByRefresh(new JSONObject(MapUtil.mapper(
                "P_DATE", P_DATE
        )),sql).stream().forEach(item -> {
            JSONObject grossProfitItem = (JSONObject) item;
            GrossProfit grossProfit = grossProfitRepository.findOne(JpaDsl.toCriteriaByEq("statisticsDate", grossProfitItem.getDate("DOCUMENT_DATE"),
                    "dept.id", grossProfitItem.getString("DEPT_ID"), "type", grossProfitItem.getString("SERVE_TYPE_NAME"), "incomeCategories",
                    grossProfitItem.getString("INCOME_CATEGORIES"))).orElse(null);
            double vipIn = grossProfitItem.get("VIP_IN") == null ? 0:grossProfitItem.getDoubleValue("VIP_IN");
            double vipOut = grossProfitItem.get("VIP_OUT") == null ? 0:grossProfitItem.getDoubleValue("VIP_OUT");
            if (Objects.isNull(grossProfit)){
                //新增项目
                grossProfit = new GrossProfit();
                //待记账金额
                grossProfit.setUnBillAmount(0);
                //台次
                grossProfit.setTimes(grossProfitItem.getDoubleValue("TIMES"));
                //成本
                grossProfit.setAmtCost(grossProfitItem.getDoubleValue("COST"));
                //营业额
                grossProfit.setAmtSale(grossProfitItem.getDoubleValue("PRICE_TOTAL"));
                //项目
                grossProfit.setType(grossProfitItem.getString("SERVE_TYPE_NAME"));
                //毛利率
                grossProfit.setProfitRate(grossProfitItem.getDoubleValue("GROSS_RATE"));
                //统计日期
                grossProfit.setStatisticsDate(grossProfitItem.getDate("DOCUMENT_DATE"));
                //记账金额
                grossProfit.setBillAmount(grossProfitItem.getDoubleValue("PRICE_TOTAL"));
                //毛利
                grossProfit.setAmtProfit(grossProfitItem.getDoubleValue("GROSS_PROFIT"));
                //工时成本
                grossProfit.setManHourCost(grossProfitItem.getDoubleValue("MAN_HOUR_COST"));
                //配件成本
                grossProfit.setAccessoryCost(grossProfitItem.getDoubleValue("ACCESSORY_COST"));
                //收入大类
                grossProfit.setIncomeCategories(grossProfitItem.getString("INCOME_CATEGORIES"));
                //耗材成本
                grossProfit.setAmtMaterialCost(grossProfitItem.getDoubleValue("CONSUMABLE_USE"));
                //部门
                grossProfit.setDept(deptRepository.findOne(grossProfitItem.getString("DEPT_ID")));
                //公司
                grossProfit.setCompany(partyRoleRepository.findOne(grossProfitItem.getString("COMPANY_ID")));
                //平台管理费
                grossProfit.setPlatformManagementFee(grossProfitItem.getDoubleValue("PLATFORM_MANAGEMENT_FEE"));
                //供应链管理费
                grossProfit.setSupplyChainManagementFee(grossProfitItem.getDoubleValue("SUPPLY_CHAIN_MANAGEMENT_FEE"));
                //会员联盟结算-收入
                grossProfit.setCrossCompanyIncome(vipIn);
                //会员联盟结算-支出
                grossProfit.setCrossCompanyPay(vipOut);
                grossProfitRepository.saveAndFlush(grossProfit);
            }else {
                //刷新成本和毛利
                //待记账金额
                grossProfit.setUnBillAmount(Arith.sub(grossProfit.getUnBillAmount(), grossProfitItem.getDoubleValue("PRICE_TOTAL")));
                //记账金额
                grossProfit.setBillAmount(Arith.add(grossProfit.getBillAmount(), grossProfitItem.getDoubleValue("PRICE_TOTAL")));
                //成本
                grossProfit.setAmtCost(Arith.add(grossProfit.getAmtCost(), grossProfitItem.getDoubleValue("COST")));
                //耗材成本
                grossProfit.setAmtMaterialCost(Arith.add(grossProfit.getAmtMaterialCost(), grossProfitItem.getDoubleValue("CONSUMABLE_USE")));
                //配件成本
                grossProfit.setAccessoryCost(Arith.add(grossProfit.getAccessoryCost(), grossProfitItem.getDoubleValue("ACCESSORY_COST")));
                //工时成本
                grossProfit.setManHourCost(Arith.add(grossProfit.getManHourCost(), grossProfitItem.getDoubleValue("MAN_HOUR_COST")));
                //供应链管理费
                grossProfit.setSupplyChainManagementFee(Arith.add(grossProfit.getSupplyChainManagementFee(), grossProfitItem.getDoubleValue("SUPPLY_CHAIN_MANAGEMENT_FEE")));
                //平台管理费
                grossProfit.setPlatformManagementFee(Arith.add(grossProfit.getPlatformManagementFee(), grossProfitItem.getDoubleValue("PLATFORM_MANAGEMENT_FEE")));
                //会员联盟结算-收入
                grossProfit.setCrossCompanyIncome(grossProfit.getCrossCompanyIncome()+vipIn);
                //会员联盟结算-支出
                grossProfit.setCrossCompanyPay(grossProfit.getCrossCompanyPay()+vipOut);
                //毛利
                grossProfit.setAmtProfit(grossProfit.getAmtSale() - grossProfit.getAmtCost() - grossProfit.getPlatformManagementFee() - grossProfit.getSupplyChainManagementFee() +grossProfit.getCrossCompanyIncome()+grossProfit.getCrossCompanyPay());
                //毛利率
                grossProfit.setProfitRate(grossProfit.getAmtSale() == 0 ? 0 : grossProfit.getAmtProfit() / (grossProfit.getAmtSale()+vipIn+vipOut));

                grossProfitRepository.saveAndFlush(grossProfit);
            }
        });
    }

}
